package com.xbongbong.saas.help;


import com.alibaba.dingtalk.openapi.exception.OApiException;
import com.alibaba.dingtalk.openapi.helper.AuthHelper;
import com.alibaba.dingtalk.openapi.helper.DepartmentHelper;
import com.alibaba.dingtalk.openapi.helper.DingTalkPageHelper;
import com.alibaba.dingtalk.openapi.helper.Env;
import com.alibaba.dingtalk.openapi.helper.MicroAppHelper;
import com.alibaba.dingtalk.openapi.helper.UserHelper;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.util.OrganizationUtil;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserDepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserDepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 公司可见范围
 * @author kaka
 */
@Component
public class CompanyVisibleScopesHelper {
    private static final Logger LOG = LoggerFactory.getLogger(CompanyVisibleScopesHelper.class);

    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private UserModel userModel;
    @Resource
    private UserDepartmentModel userDepartmentModel;
    @Resource
    private AuthHelper authHelper;

    /**
     * 获取公司实际使用人情况 xbb可见范围设置&钉钉可见范围
     *
     * @param corpid 公司ID
     * @author kaka
     * @date 2018/1/17
     */
    public void setCompanyVisibleScopes(String corpid) throws XbbException {
        syncDingtalkVisibleScopes(corpid);
    }

    /**
     *
     * @param corpid 公司id
     * @param depIds 部门id列表
     * @param userIds
     * 创建时间 2019/1/23 7:30 PM
     * 修改时间 2019/1/23 7:30 PM
     * @author chy
     * @since v3.37
     * @version v3.37
     */
    private void syncFromDD(String corpid, List<Long> depIds, List<String> userIds, String accessToken) {
        //可见范围中的部门，包含子部门，用于同步其中的员工
        List<Long> depIdInRecursive = new ArrayList<>();
        if (depIds != null) {
            //从数据库的部门树中获取所有需要更新的部门id
            depIdInRecursive = getDepartmentIdsByRegexp(depIds, corpid);
            Map<Long, DepartmentEntity> deptsMap = departmentModel.getDeptsMap(corpid, depIdInRecursive);
            //从钉钉获取部门详情
            for(Long authDepId : depIdInRecursive) {
                DepartmentEntity depEntity = deptsMap.get(authDepId);
                saveDepToDb(corpid, depEntity, accessToken, authDepId);
            }
        }
        //获取员工
        fetchUserFromDept(depIdInRecursive, accessToken, corpid, userIds);
    }

    /**
     * 修正部门id和路由
     * 1、未挂在根部门的游离部门需要挂在根部门上
     * 2、当授权人不在可见部门中，需要将部门展示出来，此时，其下的部门所挂的节点会错误，需要修正
     * @param corpid
     */
    private void correctDepIdRouter(String corpid) {
        List<DepartmentEntity> departmentList = new ArrayList<>();
        try {
            departmentList = departmentModel.findAllDepartment(corpid, false);
        } catch (Exception e) {
            LOG.error("correctDepIdRouter error：", e);
        }
        Set<Long> depIdSet = new HashSet<>();
        for (DepartmentEntity department : departmentList) {
            depIdSet.add(department.getId());
        }
        // 构建depId,pid键值对，用于计算depIdRouter
        Map<Long, Long> depIdPIdMap = new HashMap<>();
        //将异常的父部门修正，父部门不在depIdSet中，则设置未1
        for (DepartmentEntity department : departmentList) {
            Long parentId = department.getParentId();
            //department为根部门或者父部门在depIdSet中
            if (depIdSet.contains(parentId) || Objects.equals(parentId, 0L)) {
                depIdPIdMap.put(department.getId(), department.getParentId());
                continue;
            }
            //父部门异常时，将父部门设置为根部门
            department.setParentId(1L);
            depIdPIdMap.put(department.getId(), department.getParentId());
        }
        for (DepartmentEntity department : departmentList) {
            OrganizationUtil.setDepIdRouter(department, depIdPIdMap);
        }
        departmentModel.updateBatch(departmentList, corpid);
    }

    private void saveDepToDb(String corpid, DepartmentEntity depEntity, String accessToken, Long authDepId) {
        boolean insertDepartment = false;
        if (depEntity == null) {
            depEntity = new DepartmentEntity();
            depEntity.setCorpid(corpid);
            insertDepartment = true;
        }
        JSONObject department = null;
        try {
            department = DepartmentHelper.getDepartment(accessToken,
                    authDepId.toString());
        } catch (OApiException e) {
            LOG.error("DepartmentHelper.getDepartment error", e);
        }

        if (department == null || department.getIntValue("errcode") != 0) {
            //没法进行下去了，报个错吧
            LOG.error("授权节点获取失败，没法创造节点插入" + " department:" + department);
            return ;
        } else {
            // 将有效的部门ID加入列表
            depEntity.formatDepartmentData(department, false);
            depEntity.setId(authDepId);
        }
        // 设置del为0
        depEntity.setDel(0);
        // 此处id不会是0所以不要用save
        try {
            if (insertDepartment) {
                // 存入[插入队列]
                departmentModel.insert(depEntity);
            } else {
                departmentModel.update(depEntity);
            }
        } catch (XbbException e) {
            LOG.error("部门插入或更新出错", e);
        }

    }

    /**
     * 获取授权公司的所有员工信息并存入数据库 通过部门员工列表获取
     * 这个方法是完全没有改动的
     * @param depIdList 部门id（父部门及其下面的所有子部门）
     * @param accessToken
     * @param corpId
     * @throws OApiException
     */
    private void fetchUserFromDept(final List<Long> depIdList,
                                   final String accessToken, final String corpId, final List<String> authUserList) {
        Integer fetchStartTime = DateUtil.getInt();
        // 是否有更多记录，部门员工列表接口
        DingTalkPageHelper pageHelper;
        Map<String, UserEntity> needMergeUserMap = new HashMap<>();
        Map<String, UserEntity> userInDBMap = getAllUserByCorpId(corpId);
        for (Long depId : depIdList) {
            if (depId != null && depId > 0) {
                pageHelper = new DingTalkPageHelper(0);
                /*
                 * 分页查询数据
                 */
                while (pageHelper.getHasMore()) {
                    /*
                     * 获取部门员工列表,简单员工列表接口，主要包含员工id和员工姓名
                     */
                    JSONArray userList = null;
                    try {
                        userList = UserHelper.getUserDetails(accessToken,
                                depId, pageHelper);
                    } catch (Exception e) {
                        LOG.error("获取部门下员工失败！", e);
                        continue ;
                    }
                    if (userList != null && userList.size() > 0) {
                        for (int i = 0; i < userList.size(); i++) {
                            JSONObject user = userList.getJSONObject(i);
                            String userId = user.getString("userid");
                            boolean isLeader = user.getBooleanValue("isLeader");
                            Long order = user.getLong("order");
                            String userDepts = user.getString("department");
                            JSONArray depIds = JSONArray.parseArray(userDepts);
                            if (depIds.size() <= 1) { // 如果只在一个部门则直接处理插入或更新数据库
                                saveUser(corpId, userId, depId, user,
                                        userInDBMap);
                            } else {
                                UserEntity cachedUser = needMergeUserMap
                                        .get(userId);
                                if (cachedUser == null) {
                                    cachedUser = new UserEntity();
                                    cachedUser
                                            .formatUserData(user, depId, true);

                                    needMergeUserMap.put(userId, cachedUser);
                                } else {
                                    String orderInDepts = cachedUser
                                            .getOrderInDepts();
                                    String isLeaderInDepts = cachedUser
                                            .getIsLeaderInDepts();
                                    String departments = cachedUser
                                            .getDepartment();

                                    // 解析
                                    JSONArray depIdArray = JSONArray
                                            .parseArray(departments);
                                    Map<Long, Long> orderInDeptsJson = JSON
                                            .parseObject(
                                                    orderInDepts,
                                                    new TypeReference<Map<Long, Long>>() {
                                                    });
                                    Map<Long, Boolean> isLeaderInDeptsJson = JSON
                                            .parseObject(
                                                    isLeaderInDepts,
                                                    new TypeReference<Map<Long, Boolean>>() {
                                                    });

                                    orderInDeptsJson.put(depId, order);
                                    isLeaderInDeptsJson.put(depId, isLeader);

                                    cachedUser.setOrderInDepts(JSON
                                            .toJSONString(orderInDeptsJson));
                                    cachedUser.setIsLeaderInDepts(JSON
                                            .toJSONString(isLeaderInDeptsJson));

                                    if (depIdArray.size() == isLeaderInDeptsJson
                                            .size()) {
                                        // 模拟成员工详情接口返回的数据
                                        user.put("orderInDepts",
                                                cachedUser.getOrderInDepts());
                                        user.put("isLeaderInDepts",
                                                cachedUser.getIsLeaderInDepts());

                                        saveUser(corpId, userId, null, user,
                                                userInDBMap);
                                        needMergeUserMap.remove(userId);
                                        //单独授权的人员部门逻辑处理完成的移除
                                        authUserList.remove(userId);
                                    }
                                }
                            }

                        }
                    }
                }
            }
        }

        //将一些所在部门没有完全授权的员工[指员工在多个部门，但是公司授权应用时只授权了部分部门]
        if(needMergeUserMap.size() > 0) {
            for(Map.Entry<String, UserEntity> entry : needMergeUserMap.entrySet()) {
                //改departments值，并插入或更新
                UserEntity restUser = entry.getValue();
                String isLeaderInDepts = restUser.getIsLeaderInDepts();
                String departments = restUser.getDepartment();

                // 解析
                List<Long> depIdArray = JSONArray.parseArray(departments, Long.class);
                Map<Long, Boolean> isLeaderInDeptsJson = JSON.parseObject(
                        isLeaderInDepts,
                        new TypeReference<Map<Long, Boolean>>() {
                        });

                Iterator<Long> depIdIter = depIdArray.iterator();
                while(depIdIter.hasNext()){
                    Long nextDepId = depIdIter.next();
                    if(!isLeaderInDeptsJson.containsKey(nextDepId)) {
                        depIdIter.remove();
                    }
                }

                //设置筛除后的depId
                restUser.setDepartment(JSON.toJSONString(depIdArray));
                saveUser(corpId, restUser.getUserId(), null, restUser,
                        userInDBMap);
            }
        }

        //钉钉通过过来游离用户的所属部门id集合
        Set<Long> tempDepIdSet = new HashSet<>();
        //剩余的孤立节点，强制挂到公司节点下
        if(authUserList != null && authUserList.size() > 0) {
            //按逻辑这边的节点应该和上面操作的needMergeUserMap及只在一个部门的用户不会有重合关系
            for(String authUserId : authUserList) {
                UserEntity authUser = userInDBMap.get(authUserId);
                JSONObject authUserJson;
                try {
                    authUserJson = UserHelper.getUser(accessToken, authUserId, corpId);
                } catch(Exception e) {
                    LOG.error("获取用户信息/user/get时出错，userId=" + authUserId, e);
                    continue;
                }
                if (authUserJson == null || authUserJson.getIntValue("errcode") != 0) {
                    continue;
                }
                boolean insertUser = false;
                if(authUser == null) {
                    authUser = new UserEntity();
                    authUser.setCorpid(corpId);
                    authUser.setIsPushMessage(1);
                    insertUser = true;
                }
                authUser.formatUserData(authUserJson, null, insertUser);
                authUser.setIsVisible(1);
                authUser.setDel(0);
                getDepId(tempDepIdSet, authUser.getDepartment());
                if(StringUtil.isEmpty(authUser.getCorpid())) {
                    authUser.setCorpid(corpId);
                }
                // 此处id不会是0所以不要用save
                try {
                    if (insertUser) {
                        userModel.insert(authUser);
                    } else {
                        userModel.update(authUser);
                    }
                } catch (Exception e) {
                    LOG.error("用户保存失败", e);
                }
                // 保存用户部门关系表数据
                saveUserDeparment(authUser, corpId);
            }
        }
        //需要将del置为0的部门id集合
        Set<Long> updateDepIdSet = new HashSet<>();

        tempDepIdSet.add(-1L);
        Map<String,Object> param = new HashMap<>();
        param.put("corpid", corpId);
        param.put("idIn", tempDepIdSet);
        List<DepartmentEntity> departmentEntityList = departmentModel.findEntitys(param);
        for(DepartmentEntity department : departmentEntityList){
            String depIdRouter = department.getDepIdRouter();
            if(StringUtil.isEmpty(depIdRouter)){
                continue;
            }
            String[] depIdStrArray = depIdRouter.split("\\|");
            for(String depIdStr : depIdStrArray){
                if(StringUtil.isEmpty(depIdStr)){
                    continue;
                }
                updateDepIdSet.add(Long.parseLong(depIdStr));
            }
        }
        if(!updateDepIdSet.isEmpty()){
            Integer del = 0;
            Integer nowInt = DateUtil.getInt();
            List<Long> idIn = new ArrayList<>(updateDepIdSet);

            departmentModel.batchUpdateDel(del, nowInt, idIn, corpId);
        }


        //删除组织架构同步过程中没有更新的数据，即不在授权范围内或已删除的数据
        deleteInfoAfterSync(corpId, fetchStartTime);
    }

    /**
     * 将游离的员工部门添加到tempDepIdSet
     * @param tempDepIdSet
     * @param department
     * 创建时间 2019/2/1 4:50 PM
     * 修改时间 2019/2/1 4:50 PM
     * @author chy
     * @since v3.37
     * @version v3.37
     */
    private void getDepId(Set<Long> tempDepIdSet, String department) {

        if(StringUtil.isEmpty(department)){
            return;
        }

        JSONArray depIds = null;

        try {
            depIds = JSONArray.parseArray(department);
        } catch (Exception e) {
            LOG.error("JSONArray.parseArray(department)失败！", e);
            return;
        }

        for (int i = 0; i < depIds.size(); i++) {
            Long depId = depIds.getLong(i);
            tempDepIdSet.add(depId);
        }
    }

    /**
     * 保存或更新用户实体
     * @param corpId
     * @param userId
     * @param depId
     * @param user
     * @param userInDBMap
     * kaka
     * 2016年12月28日 上午10:18:59
     */
    private void saveUser(String corpId, String userId, Long depId, UserEntity user, Map<String, UserEntity> userInDBMap) {
        if(user == null) {
            //user不能为null
            return;
        }
        boolean insertUser = false;
        if (!userInDBMap.containsKey(userId)) {
            user.setCorpid(corpId);
            insertUser = true;
        } else {
            UserEntity oldUser = userInDBMap.get(userId);
            user.setAddTime(oldUser.getAddTime());
            user.setRoleIds(oldUser.getRoleIds());
            user.setIsPushMessage(oldUser.getIsPushMessage());
            user.setPassportId(oldUser.getPassportId());
            user.setCorpid(corpId);
        }
        // 设置del为0
        user.setDel(0);
        if(StringUtil.isEmpty(user.getCorpid())) {
            user.setCorpid(corpId);
        }
        // 此处id不会是0所以不要用save
        try {
            if (insertUser) {
                userModel.insert(user);
            } else {
                userModel.update(user);
            }
        } catch (Exception e) {
            LOG.error("用户保存失败", e);
        }
        // 保存用户部门关系表数据
        saveUserDeparment(user, corpId);
    }

    /**
     * 获取某个公司的“钉钉”可见范围
     * accessToken 和 agentId在内部获取
     * @param corpid 公司ID
     * @return 返回的jsonObject中至少包含deptVisibleScopes（可见部门数组） 和 userVisibleScopes（可见员工数组）
     *
     * @author kaka
     * @date 2018/1/17
     */
    public JSONObject getDingtalkVisibleScopes(String corpid) throws Exception {
        return getDingtalkVisibleScopes(corpid, null, null);
    }

    /**
     * 获取某个公司的“钉钉”可见范围
     * @param corpid 公司ID
     * @param accessTokenParam 公司访问accessToken，若为null则在内部计算
     * @param agentIdParam 公司访问agentId，若为null则在内部计算
     * @return 返回的jsonObject中至少包含deptVisibleScopes（可见部门数组） 和 userVisibleScopes（可见员工数组）
     *
     * @author kaka
     * @date 2018/1/17
     */
    public JSONObject getDingtalkVisibleScopes(String corpid, String accessTokenParam, String agentIdParam) throws Exception {
        if(StringUtil.isEmpty(corpid)) {
            throw new IllegalArgumentException("corpid 参数不能为空");
        }

        String accessToken;
        String agentId;
        if(StringUtil.isEmpty(accessTokenParam) || StringUtil.isEmpty(agentIdParam)) {
            try {
                accessToken = authHelper.getAccessToken(corpid);
                agentId = authHelper.getAgentId(corpid, Env.DING_XBB_APP_ID);
            } catch (Exception e){
                LOG.error("syncDingtalkVisibleScopes 获取accessToken及agentId出错,corpid=" + corpid, e);
                throw e;
            }
        } else {
            accessToken = accessTokenParam;
            agentId = agentIdParam;
        }

        JSONObject retJson;
        try {
            retJson = MicroAppHelper.geVisibleScopes(accessToken, agentId);
        } catch (OApiException e) {
            LOG.error("syncCompanyConfig  MicroAppHelper.geVisibleScopes出错", e);
            throw e;
        }

        LOG.info("getDingtalkVisibleScopes MicroAppHelper.geVisibleScopes 获取结果:" + retJson.toJSONString());
        Integer errcode = retJson.getInteger("errcode");
        // 出错
        if (errcode != null && !errcode.equals(0)) {
            LOG.error("syncCompanyConfig  MicroAppHelper.geVisibleScopes出错  retJosn = " + retJson.toJSONString());
            throw new OApiException(errcode, retJson.getString("errmsg"));
        }

        return retJson;
    }

    /**
     * 按“钉钉”可见范围设置组织架构中的员工是否可见
     * @param corpid 公司ID
     *
     * @author kaka
     * @date 2018/1/11
     */
    private void syncDingtalkVisibleScopes(String corpid){
        if(StringUtil.isEmpty(corpid)) {
            throw new IllegalArgumentException("corpid 参数不能为空");
        }

        JSONObject retJson;
        try {
            retJson = getDingtalkVisibleScopes(corpid);
        } catch (Exception e) {
            LOG.error("syncDingtalkVisibleScopes getDingtalkVisibleScopes出错", e);
            return;
        }

        /*
         * 以下几种情况都是全公司:
         * {"deptVisibleScopes":[],"isHidden":false,"userVisibleScopes":[]}
         * 没有选任何部门和人 {"deptVisibleScopes":"1","isHidden":false} 微应用添加时选了全公司
         * {"deptVisibleScopes":[1],"isHidden":false,"userVisibleScopes":[]}
         * 修改微应用可见范围时选择第一级公司
         * {"deptVisibleScopes":[6604589,6604590,6604591,6616759
         * ,9268861,1],"isHidden"
         * :false,"userVisibleScopes":["0440552440847317","044626310037745767"]}
         * 修改微应用可见范围时选择第一级公司和其他几个部门或员工
         */
        // 微应用是否全公司可见
        boolean entireCompany = false;
        String deptVisibleScopes = retJson.getString("deptVisibleScopes");
        String userVisibleScopes = retJson.getString("userVisibleScopes");

        //同步组织架构时，dingding可见范围存库
        companyConfigModel.save(corpid, CompanyConfigEnum.DING_VISIBLE_SCOPES.getAlias(),
                CompanyConfigEnum.DING_VISIBLE_SCOPES.getName(), retJson.toJSONString());

        if ("1".equals(deptVisibleScopes)) {
            entireCompany = true;
        }

        List<Long> depIdIn;
        try {
            depIdIn = JSON.parseArray(deptVisibleScopes, Long.class);
        } catch (Exception e) {
            LOG.error("/dingtalk/syncCompanyConfig deptVisibleScopes List<Long>转化异常", e);
            // 这里转换出错先当做全公司处理
            depIdIn = new ArrayList<>();
        }

        if (depIdIn == null) {
            depIdIn = new ArrayList<>();
        }

        List<String> userVisibleScopesList;
        try {
            userVisibleScopesList = JSON.parseArray(userVisibleScopes, String.class);
        } catch (Exception e) {
            LOG.error("/dingtalk/syncCompanyConfig userVisibleScopes List<String>转化异常" + userVisibleScopes, e);
            userVisibleScopesList = new ArrayList<>();
        }

        if (userVisibleScopesList == null) {
            userVisibleScopesList = new ArrayList<>();
        }

        if (depIdIn.contains(1L) || (depIdIn.size() == 0 && userVisibleScopesList.size() == 0)) {
            entireCompany = true;
        }

        if (entireCompany && !depIdIn.contains(1L)) {
            //全公司可见，且部门中不包含顶级部门
            depIdIn.add(1L);
        }
        String accessToken = null;
        try {
            accessToken = authHelper.getAccessToken(corpid);
        } catch (OApiException e) {
            LOG.error("syncDingtalkVisibleScopes get accessToken error", e);
            return ;
        }
        syncFromDD(corpid, depIdIn, userVisibleScopesList, accessToken);
        //全公司
        if(entireCompany){
            userModel.updateAllVisibleByCorpId(corpid, 1);
            return;
        }
        /*
		 * 先将全公司置为可用，再排除其中非可见范围的员工[置为del=2]
		 */
        userModel.updateAllVisibleByCorpId(corpid, 1);
        //所有需要更新的用户列表
        List<String> userIdList = new ArrayList<String>();
        if(depIdIn.size() > 0) {
            List<Long> depIdInRecursive = getDepartmentIdsByRegexp(depIdIn, corpid);

            userIdList = userModel.getDepUserIdList(corpid, new HashSet<>(depIdInRecursive));
        }
        if(userVisibleScopesList.size() > 0) {
            //无重复并集
            userVisibleScopesList.removeAll(userIdList);
            userIdList.addAll(userVisibleScopesList);
        }
        if(userIdList.size() == 0) {
            //保证不空
            userIdList.add("-1");
        }
        //置是否可见标记位,将不可见的排除
        userModel.updateVisibleByCorpIdAndUserIdNotIn(corpid, 0, userIdList);

        //清理空部门，设置del=2
        departmentModel.clearEmptyDepartment(corpid);
        correctDepIdRouter(corpid);
    }

    /**
     * 获取depIdIn及其子部门的部门id集合
     * @param depIdIn 部门id列表
     * @param corpid 公司id
     * @return
     */
    private List<Long> getDepartmentIdsByRegexp(List<Long> depIdIn, String corpid){
        List<Long> depIdInRecursive = new ArrayList<>();

        if (depIdIn != null && depIdIn.size() > 0) {
            StringBuilder depIdInRegexp = new StringBuilder();
            for(int i = 0; i < depIdIn.size(); i++) {
                Long depIdTmp = depIdIn.get(i);
                depIdInRegexp.append("(\\|").append(depIdTmp).append("\\|)");
                if(i != depIdIn.size() - 1) {
                    depIdInRegexp.append("|");
                }
            }
            /*
             * 递归部门ID
             */
            depIdInRecursive = departmentModel.getDepartmentIdsByRegexp(corpid, depIdInRegexp.toString());

        }
        return depIdInRecursive;
    }

    /**
     * 从数据库中查询出公司所有user信息并放入内存
     *
     * @param corpId
     * @return
     */
    @SuppressWarnings("unchecked")
    private Map<String, UserEntity> getAllUserByCorpId(String corpId) {
        Map<String, UserEntity> userMap = new HashMap<>();
        //每页1000条
        Integer pageSize = 1000;
        Integer page = 0;
        List<UserEntity> list;
        do {
            page++;
            Map<String, Object> param = new HashMap<String, Object>();
            param.put("corpid", corpId);
            param.put("page", page);

            PageHelper pageHelper = null;
            pageHelper = PageHelperUtil.getPageHelper(param, userModel, pageSize);
            list = (List<UserEntity>) PageHelperUtil.getEntityList(param, pageHelper, userModel);
            if (list.size() > 0) {
                for (UserEntity user : list) {
                    userMap.put(user.getUserId(), user);
                }
            }else{
                break;
            }
        } while (list.size() == pageSize);
        return userMap;
    }

    /**
     * 保存用户部门关系表数据
     *
     * @param user
     * @param corpId
     */
    private void saveUserDeparment(UserEntity user, String corpId) {
        if (user == null || StringUtil.isEmpty(corpId)) {
            return;
        }

        String userId = user.getUserId();
        if (StringUtil.isEmpty(userId)) {
            return;
        }

        Map<Long, UserDepartmentEntity> userDeptsMap = new HashMap<>();

        Map<String, Object> param = new HashMap<>();
        param.put("corpid", corpId);
        param.put("userId", userId);

        List<UserDepartmentEntity> userDepts = userDepartmentModel
                .findEntitys(param);
        if (userDepts.size() > 0) {
            for (UserDepartmentEntity userDept : userDepts) {
                userDeptsMap.put(userDept.getDepartmentId(), userDept);
            }
        }

        String orderInDepts = user.getOrderInDepts();
        String isLeaderInDepts = user.getIsLeaderInDepts();
        String department = user.getDepartment();
        // 解析
        JSONArray depIds = JSONArray.parseArray(department);
        Map<Long, Long> orderInDeptsJson = JSON.parseObject(orderInDepts,
                new TypeReference<Map<Long, Long>>() {
                });
        Map<Long, Boolean> isLeaderInDeptsJson = JSON.parseObject(
                isLeaderInDepts, new TypeReference<Map<Long, Boolean>>() {
                });

        for (int i = 0; i < depIds.size(); i++) {
            Long depId = depIds.getLong(i);

            Long sort = orderInDeptsJson.get(depId);
            int isLeader = isLeaderInDeptsJson.get(depId) ? 1 : 0;

            UserDepartmentEntity userDept = userDeptsMap.get(depId);
            boolean userDeptInsert = false;
            if (userDept == null) {
                userDept = new UserDepartmentEntity();
                userDeptInsert = true;
            }
            userDept.setCorpid(corpId);
            userDept.setUserId(userId);
            userDept.setDepartmentId(depId);
            userDept.setIsLeader(isLeader);
            userDept.setSort(sort);

            // 更新修改时间
            userDept.setUpdateTime(DateUtil.getInt());
            // 将删除标记置为0
            userDept.setDel(0);

            try {
                if (userDeptInsert) {
                    userDepartmentModel.insert(userDept);
                } else {
                    userDepartmentModel.update(userDept);
                }
            } catch (XbbException e) {
                LOG.error("userDepartment保存失败", e);
            }
        }

    }

    /**
     * 根据用户JSONObject构建用户实体，插入或者更新数据库记录
     *
     * @param corpId
     * @param userId
     * @param depId
     *            为null时表示直接从用户详情接口获取的数据，而不是从部门员工详情列表获取的数据
     * @param user
     * @param userInDBMap
     *            该公司数据库中所有用户信息，转化为<userId,userEntity>形式
     */
    private void saveUser(String corpId, String userId, Long depId,
                          JSONObject user, Map<String, UserEntity> userInDBMap) {

        UserEntity userEntity = userInDBMap.get(userId);
        boolean insertUser = false;
        if (userEntity == null) {
            userEntity = new UserEntity();
            userEntity.setCorpid(corpId);
            insertUser = true;
        }
        userEntity.formatUserData(user, depId, insertUser);
        // 设置del为0
        userEntity.setDel(0);

        if(StringUtil.isEmpty(userEntity.getCorpid())) {
            userEntity.setCorpid(corpId);
        }
        // 此处id不会是0所以不要用save
        try {
            if (insertUser) {
                userModel.insert(userEntity);
            } else {
                userModel.update(userEntity);
            }
        } catch (Exception e) {
            LOG.error("用户保存失败", e);
        }
        // 保存用户部门关系表数据
        saveUserDeparment(userEntity, corpId);
    }

    /**
     * 删除组织架构同步过程中没有更新的数据，即不在授权范围内或已删除的数据
     * @param corpid 公司id
     * @param fetchStartTime 开始同步员工数据的开始时间(user&userDepartment表)
     */
    private void deleteInfoAfterSync(final String corpid, final Integer fetchStartTime) {
        // 删除员工
        userModel.clearUnauthUserByUpdateTime(corpid, fetchStartTime);
        // 删除员工部门关系
        userDepartmentModel.clearUnauthUserByUpdateTime(corpid, fetchStartTime);
    }
}

